﻿using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Reactive.Concurrency;
using System.Reactive.Subjects;
using System.Threading;
#if !WINDOWS_PHONE
using System.Threading.Tasks;
#endif

namespace System.Reactive.Linq
{
	public static partial class Observable
	{
		public static IObservable<TSource> Sample<TSource, TSample>(this IObservable<TSource> source, IObservable<TSample> sampler)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(sampler != null, null, "sampler != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Sample<TSource>(this IObservable<TSource> source, TimeSpan interval)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Sample<TSource>(this IObservable<TSource> source, TimeSpan interval, IScheduler scheduler)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Scan<TSource>(this IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(accumulator != null, null, "accumulator != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TAccumulate> Scan<TSource, TAccumulate>(this IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(accumulator != null, null, "accumulator != null");
			Contract.Ensures(Contract.Result<IObservable<TAccumulate>>() != null, null, "Contract.Result<IObservable<TAccumulate>>() != null");
			return null;
		}

		public static IObservable<TResult> Select<TSource, TResult>(this IObservable<TSource> source, Func<TSource, int, TResult> selector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(selector != null, null, "selector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> Select<TSource, TResult>(this IObservable<TSource> source, Func<TSource, TResult> selector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(selector != null, null, "selector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> SelectMany<TSource, TResult>(this IObservable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(selector != null, null, "selector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> SelectMany<TSource, TResult>(this IObservable<TSource> source, Func<TSource, IObservable<TResult>> selector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(selector != null, null, "selector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

#if !WINDOWS_PHONE
		public static IObservable<TResult> SelectMany<TSource, TResult>(this IObservable<TSource> source, Func<TSource, Task<TResult>> selector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(selector != null, null, "selector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}
#endif

		public static IObservable<TOther> SelectMany<TSource, TOther>(this IObservable<TSource> source, IObservable<TOther> other)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(other != null, null, "other != null");
			Contract.Ensures(Contract.Result<IObservable<TOther>>() != null, null, "Contract.Result<IObservable<TOther>>() != null");
			return null;
		}

		public static IObservable<TResult> SelectMany<TSource, TCollection, TResult>(this IObservable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(collectionSelector != null, null, "collectionSelector != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> SelectMany<TSource, TCollection, TResult>(this IObservable<TSource> source, Func<TSource, IObservable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(collectionSelector != null, null, "collectionSelector != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

#if !WINDOWS_PHONE
		public static IObservable<TResult> SelectMany<TSource, TCollection, TResult>(this IObservable<TSource> source, Func<TSource, Task<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(collectionSelector != null, null, "collectionSelector != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}
#endif

		public static IObservable<TResult> SelectMany<TSource, TResult>(this IObservable<TSource> source, Func<TSource, IObservable<TResult>> onNext, Func<Exception, IObservable<TResult>> onError, Func<IObservable<TResult>> onCompleted)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(onNext != null, null, "onNext != null");
			Contract.Requires(onError != null, null, "onError != null");
			Contract.Requires(onCompleted != null, null, "onCompleted != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<bool> SequenceEqual<TSource>(this IObservable<TSource> first, IObservable<TSource> second)
		{
			Contract.Requires(first != null, null, "first != null");
			Contract.Requires(second != null, null, "second != null");
			Contract.Ensures(Contract.Result<IObservable<bool>>() != null, null, "Contract.Result<IObservable<bool>>() != null");
			return null;
		}

		public static IObservable<bool> SequenceEqual<TSource>(this IObservable<TSource> first, IObservable<TSource> second, IEqualityComparer<TSource> comparer)
		{
			Contract.Requires(first != null, null, "first != null");
			Contract.Requires(second != null, null, "second != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IObservable<bool>>() != null, null, "Contract.Result<IObservable<bool>>() != null");
			return null;
		}

		public static TSource Single<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			return default(TSource);
		}

		public static TSource Single<TSource>(this IObservable<TSource> source, Func<TSource, bool> predicate)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(predicate != null, null, "predicate != null");
			return default(TSource);
		}

		public static IObservable<TSource> SingleAsync<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> SingleAsync<TSource>(this IObservable<TSource> source, Func<TSource, bool> predicate)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(predicate != null, null, "predicate != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static TSource SingleOrDefault<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			return default(TSource);
		}

		public static TSource SingleOrDefault<TSource>(this IObservable<TSource> source, Func<TSource, bool> predicate)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(predicate != null, null, "predicate != null");
			return default(TSource);
		}

		public static IObservable<TSource> SingleOrDefaultAsync<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> SingleOrDefaultAsync<TSource>(this IObservable<TSource> source, Func<TSource, bool> predicate)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(predicate != null, null, "predicate != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Skip<TSource>(this IObservable<TSource> source, int count)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(count >= 0, null, "count >= 0");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> SkipLast<TSource>(this IObservable<TSource> source, int count)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(count >= 0, null, "count >= 0");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> SkipUntil<TSource, TOther>(this IObservable<TSource> source, IObservable<TOther> other)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(other != null, null, "other != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> SkipWhile<TSource>(this IObservable<TSource> source, Func<TSource, bool> predicate)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(predicate != null, null, "predicate != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> SkipWhile<TSource>(this IObservable<TSource> source, Func<TSource, int, bool> predicate)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(predicate != null, null, "predicate != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<Unit> Start(Action action)
		{
			Contract.Requires(action != null, null, "action != null");
			Contract.Ensures(Contract.Result<IObservable<Unit>>() != null, null, "Contract.Result<IObservable<Unit>>() != null");
			return null;
		}

		public static IObservable<TSource> Start<TSource>(Func<TSource> function)
		{
			Contract.Requires(function != null, null, "function != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<Unit> Start(Action action, IScheduler scheduler)
		{
			Contract.Requires(action != null, null, "action != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<Unit>>() != null, null, "Contract.Result<IObservable<Unit>>() != null");
			return null;
		}

		public static IObservable<TSource> Start<TSource>(Func<TSource> function, IScheduler scheduler)
		{
			Contract.Requires(function != null, null, "function != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

#if !WINDOWS_PHONE
		public static IObservable<TSource> StartAsync<TSource>(Func<Task<TSource>> functionAsync)
		{
			Contract.Requires(functionAsync != null, null, "functionAsync != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<Unit> StartAsync(Func<Task> actionAsync)
		{
			Contract.Requires(actionAsync != null, null, "actionAsync != null");
			Contract.Ensures(Contract.Result<IObservable<Unit>>() != null, null, "Contract.Result<IObservable<Unit>>() != null");
			return null;
		}

		public static IObservable<Unit> StartAsync(Func<CancellationToken, Task> actionAsync)
		{
			Contract.Requires(actionAsync != null, null, "actionAsync != null");
			Contract.Ensures(Contract.Result<IObservable<Unit>>() != null, null, "Contract.Result<IObservable<Unit>>() != null");
			return null;
		}

		public static IObservable<TSource> StartAsync<TSource>(Func<CancellationToken, Task<TSource>> functionAsync)
		{
			Contract.Requires(functionAsync != null, null, "functionAsync != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}
#endif

		public static IObservable<TSource> StartWith<TSource>(this IObservable<TSource> source, params TSource[] values)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(values != null, null, "values != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> StartWith<TSource>(this IObservable<TSource> source, IScheduler scheduler, params TSource[] values)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Requires(values != null, null, "values != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IDisposable Subscribe<TSource>(this IEnumerable<TSource> source, IObserver<TSource> observer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(observer != null, null, "observer != null");
			Contract.Ensures(Contract.Result<IDisposable>() != null, null, "Contract.Result<IDisposable>() != null");
			return null;
		}

		public static IDisposable Subscribe<TSource>(this IEnumerable<TSource> source, IObserver<TSource> observer, IScheduler scheduler)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(observer != null, null, "observer != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IDisposable>() != null, null, "Contract.Result<IDisposable>() != null");
			return null;
		}

		public static IObservable<TSource> SubscribeOn<TSource>(this IObservable<TSource> source, IScheduler scheduler)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> SubscribeOn<TSource>(this IObservable<TSource> source, SynchronizationContext context)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(context != null, null, "context != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<decimal?> Sum(this IObservable<decimal?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<decimal?>>() != null, null, "Contract.Result<IObservable<decimal?>>() != null");
			return null;
		}

		public static IObservable<decimal> Sum(this IObservable<decimal> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<decimal>>() != null, null, "Contract.Result<IObservable<decimal>>() != null");
			return null;
		}

		public static IObservable<double?> Sum(this IObservable<double?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<double?>>() != null, null, "Contract.Result<IObservable<double?>>() != null");
			return null;
		}

		public static IObservable<double> Sum(this IObservable<double> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<double>>() != null, null, "Contract.Result<IObservable<double>>() != null");
			return null;
		}

		public static IObservable<float?> Sum(this IObservable<float?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<float?>>() != null, null, "Contract.Result<IObservable<float?>>() != null");
			return null;
		}

		public static IObservable<float> Sum(this IObservable<float> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<float>>() != null, null, "Contract.Result<IObservable<float>>() != null");
			return null;
		}

		public static IObservable<int?> Sum(this IObservable<int?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<int?>>() != null, null, "Contract.Result<IObservable<int?>>() != null");
			return null;
		}

		public static IObservable<int> Sum(this IObservable<int> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<int>>() != null, null, "Contract.Result<IObservable<int>>() != null");
			return null;
		}

		public static IObservable<long?> Sum(this IObservable<long?> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<long?>>() != null, null, "Contract.Result<IObservable<long?>>() != null");
			return null;
		}

		public static IObservable<long> Sum(this IObservable<long> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<long>>() != null, null, "Contract.Result<IObservable<long>>() != null");
			return null;
		}

		public static IObservable<TSource> Switch<TSource>(this IObservable<IObservable<TSource>> sources)
		{
			Contract.Requires(sources != null, null, "sources != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Synchronize<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}

		public static IObservable<TSource> Synchronize<TSource>(this IObservable<TSource> source, object gate)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(gate != null, null, "gate != null");
			Contract.Ensures(Contract.Result<IObservable<TSource>>() != null, null, "Contract.Result<IObservable<TSource>>() != null");
			return null;
		}
	}
}